package com.me.study.concurrent.线程通信;

import com.me.common.util.SleepUtil;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.junit.Before;
import org.junit.Test;

/**
 * 读写锁：
 * TODO 1，写饥饿存在吗？好像不
 * 2，读读共享
 * 3，写写互斥
 * 4，读写互斥
 *
 * @author ME
 * @date   2020/1/8
 */
public class TestReadWriteLock {
    private static ReentrantReadWriteLock lock;

    @Test
    public void writeHunger() {
        System.out.println("---------写饥饿好像不存在，读锁共享不排队，写锁才排队---------");
        int i = 1;

        TestReadWriteLock readWriteLock = new TestReadWriteLock();
        new Thread(readWriteLock::read, "Read-Thread-" + i++).start();

        SleepUtil.ms(50);
        for (int j = 0; j < 5; j++) {
            new Thread(readWriteLock::read, "Read-Thread-" + i++).start();
        }
        new Thread(readWriteLock::write, "Write-Thread-1").start();
        new Thread(readWriteLock::write, "Write-Thread-2").start();

        for (int j = 0; j < 5; j++) {
            new Thread(readWriteLock::read, "Read-Thread-" + i++).start();
        }

        SleepUtil.seconds(5);
    }

    @Test
    public void readRead() {
        System.out.println("---------读读共享---------");
        TestReadWriteLock readWriteLock = new TestReadWriteLock();
        new Thread(() -> {
            readWriteLock.read();
        }, "Read-Thread1").start();
        new Thread(readWriteLock::read, "Read-Thread2").start();

        // Junit 开启的子线程 会在主线程停止后被直接杀掉，so睡眠
        SleepUtil.seconds(2);
    }

    @Test
    public void writeWrite() {
        System.out.println("---------写写互斥---------");
        TestReadWriteLock readWrite = new TestReadWriteLock();
        new Thread(() -> readWrite.write(), "Write-Thread1").start();
        new Thread(readWrite::write, "Write-Thread2").start();

        // Junit 开启的子线程 会在主线程停止后被直接杀掉，so睡眠
        SleepUtil.seconds(2);
    }

    @Test
    public void readWrite() {
        System.out.println("---------读写互斥---------");
        TestReadWriteLock readWrite = new TestReadWriteLock();
        new Thread(readWrite::read, "Read-Thread").start();
        new Thread(readWrite::write, "Write-Thread").start();

        // Junit 开启的子线程 会在主线程停止后被直接杀掉，so睡眠
        SleepUtil.seconds(2);
    }

    @Before
    public void before() {
        TestReadWriteLock.lock = new ReentrantReadWriteLock();
        System.out.println();
    }

    public void write() {
        lock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " start");
            SleepUtil.ms(1000);
            System.out.println(Thread.currentThread().getName() + " end");
        } finally {
            lock.writeLock().unlock();
        }

    }

    public void read() {
        lock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " start");
            SleepUtil.ms(1000);
            System.out.println(Thread.currentThread().getName() + " end");
        } finally {
            lock.readLock().unlock();
        }

    }

}
